'''
FilePath: \src\model\parallel_reverse.py
Description: 逆序并行算法

Author: xy
Date: 2025-06-11 15:44:59
Version: 
'''

def decode_chromosome(chromosome, process_time, transport_time, last_process_start_time,list_stage,start_index):
    '''
    description: 逆序并行算法的实现
    param {*} chromosome
    param {*} process_time
    param {*} transport_time
    param {*} last_process_start_time
    param {*} list_stage
    param {*} start_index
    return {*}
    '''
    time_table = [[0 for i in range(len(chromosome[0]))] for j in range(len(chromosome))]

    for i in range(len(start_index)-1):  # 浇次
        stage=list_stage[i]# 阶段
        for j in range(start_index[i],start_index[i+1]):
            time_table[j][-1]=last_process_start_time[j]  # 第一阶段加工时间
            for s in range(len(stage)-2,-1,-1):
                time_table[j][stage[s]]=time_table[j][stage[s+1]]-process_time[j][stage[s]]-transport_time[j][stage[s+1]]
                
    return(time_table)

def resolve_conflicts(time_table,process_time, transport_time,population,info):
    '''
    description: 冲突消解
    '''
    stage_m=[[] for i in range(info.data.num_stage)]
    machine_usage = [[] for i in range(info.data.num_device)]  # 机器的使用时间
    resolved_time_table = [row.copy() for row in time_table]
    start_index=info.start_index
    list_stage=info.list_stage
    M_bs=info.M_bs
    list_stage_withnull=info.list_stage_withnull

    #获取机器加工顺序
    for s in range(len(list_stage_withnull)):
        for i in range(len(list_stage_withnull[s])):
            if list_stage_withnull[s][i]!=-1:
                for machine in M_bs[s][list_stage_withnull[s][i]]:
                    machine_id=info.data.stage_device[list_stage_withnull[s][i]][0]+machine
                    if machine_id not in stage_m[i]:
                        stage_m[i].append(machine_id)

    #获取各个机器的使用时间
    for o in range(len(start_index)-1):
        for i in range(start_index[o],start_index[o+1]):  # 炉次
            for j in range(len(time_table[0])):  # 阶段
                if population[i][j]!=0:
                    machine=info.data.stage_device[j][population[i][j]-1]
                    machine_usage[machine].append([time_table[i][j],time_table[i][j]+process_time[i][j],i,j,o])  
             
    for stage in stage_m:
        for machine_id in stage:
            usages = machine_usage[machine_id]
            # 按开始时间排序，若时间相同，则浇次靠前的优先
            usages.sort(key=lambda x: (x[0]))   
            # 检查并解决冲突,遍历机器加工表
            for i in range(1, len(usages)):
                prev_end = usages[i-1][1]
                curr_start = usages[i][0]            
                if curr_start < prev_end:  # 检测到冲突（前一个工序完成时间大于后一个工序开始时间）
                    # 计算需要延迟的时间
                    delay = prev_end - curr_start
                    # 更新当前任务的开始时间
                    cast_idx = usages[i][2]
                    stage_idx = usages[i][3]
                    resolved_time_table[cast_idx][stage_idx] += delay

                    stage_list=list_stage[usages[i][4]]#后续阶段编号
                    # 更新后续阶段的时间
                    index = stage_list.index(stage_idx)
                    
                    for next_stage in range(index+1, len(stage_list)):
                        next_stage_idx = stage_list[next_stage]
                        resolved_time_table[cast_idx][next_stage_idx] += delay
                        # 更新对应机器加工时间表，找到下阶段相应炉次
                        machine=info.data.stage_device[next_stage_idx][population[cast_idx][next_stage_idx]-1]#获取之后阶段机器
                        choose_usages=machine_usage[machine]#相应的机器时间表
                        #更新对应机器时间表
                        for u_idx, usage in enumerate(choose_usages):
                            if usage[2] == cast_idx and usage[3] == next_stage_idx:
                                choose_usages[u_idx] = [
                                    usage[0] + delay,
                                    usage[1] + delay,
                                    usage[2],
                                    usage[3],
                                    usage[4]
                                ]
                    
                    # 更新机器使用记录
                    usages[i] = [usages[i][0]+delay, usages[i][1]+delay, cast_idx, stage_idx, usages[i][4]]

    # 更新连铸机，保证连浇
    for machine_id in stage_m[-1]:
        usages = machine_usage[machine_id]
        # 修改为根据每个子元素的第一个和最后一个元素排序
        usages.sort(key=lambda x: x[2])
        for i in range(1, len(usages)):
            for i in range(1, len(usages)):
                prev_end = usages[i-1][1]
                curr_start = usages[i][0]           
                if curr_start < prev_end:  # 检测到冲突
                    # 计算需要延迟的时间
                    delay = prev_end - curr_start
                    # 更新当前任务的开始时间
                    cast_idx = usages[i][2]
                    stage_idx = usages[i][3]
                    resolved_time_table[cast_idx][stage_idx] += delay
                    usages[i] = [usages[i][0]+delay, usages[i][1]+delay, cast_idx, stage_idx, usages[i][4]]
    
    for machine_id in stage_m[-1]:
        usages = machine_usage[machine_id]
        for i in range(len(usages)-2,-1,-1):
            if usages[i][4]==usages[i+1][4]:
                if usages[i][1]<usages[i+1][0]:
                    delay=usages[i+1][0]-usages[i][1]
                    cast_idx = usages[i][2]
                    stage_idx = usages[i][3]
                    resolved_time_table[cast_idx][stage_idx] += delay
                    usages[i] = [usages[i][0]+delay, usages[i][1]+delay, cast_idx, stage_idx, usages[i][4]]
    
    # 优化消解冲突后的结果(让空隙减少，比如最后一阶段20开始，前一阶段10结束，就可以调整)
    for stage in range(len(stage_m)-2,-1,-1):
        for machine_id in stage_m[stage]:
            usages = machine_usage[machine_id]
            for i in range(len(usages)-1,-1,-1):
                    cast_idx = usages[i][2]
                    stage_idx = usages[i][3]
                    stage_list=list_stage[usages[i][4]]
                    index = stage_list.index(stage_idx)
                    next_stage=stage_list[index+1]
                    time1=resolved_time_table[cast_idx][next_stage]-transport_time[cast_idx][next_stage]
                    #判断两个阶段相差时间和同机器相邻工序相差时间
                    if i!=len(usages)-1:
                        time2=usages[i+1][0]
                    else:
                        time2=time1
                    time=min(time1,time2)
                    #进行相应改动
                    delay=time-usages[i][1]
                    resolved_time_table[cast_idx][stage_idx] += delay
                    usages[i] = [usages[i][0]+delay, usages[i][1]+delay, cast_idx, stage_idx, usages[i][4]]
                    
    return resolved_time_table,machine_usage